home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / mush6.4 / part05 < prev    next >
Encoding:
Internet Message Format  |  1989-03-12  |  45.1 KB

  1. Subject:  v18i027:  Mail user's shell version 6.4, Part05/19
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dan Heller <island!argv@sun.com>
  7. Posting-number: Volume 18, Issue 27
  8. Archive-name: mush6.4/part05
  9.  
  10.  
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 5 (of 19)."
  19. # Contents:  doproc.c file.c signals.c strings.c
  20. # Wrapped by rsalz@papaya.bbn.com on Mon Mar 13 19:25:11 1989
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'doproc.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'doproc.c'\"
  24. else
  25. echo shar: Extracting \"'doproc.c'\" \(12131 characters\)
  26. sed "s/^X//" >'doproc.c' <<'END_OF_FILE'
  27. X/* @(#)doproc.c        (c) copyright    10/18/86 (Dan Heller) */
  28. X
  29. X/* do main panel item procedures */
  30. X#include "mush.h"
  31. X
  32. Xrespond_mail(item, value, event)
  33. XPanel_item item;
  34. Xint value;
  35. Xstruct inputevent *event;
  36. X{
  37. X    char buf[80];
  38. X
  39. X    if (value == 4)
  40. X    return help(panel_sw->ts_windowfd, "respond", tool_help);
  41. X    if (ison(glob_flags, IS_GETTING)) {
  42. X    print("Finish editing current message first");
  43. X    return;
  44. X    }
  45. X    if (!msg_cnt) {
  46. X    print("No messages to respond to.\n");
  47. X    return;
  48. X    }
  49. X    print("Responding to message %d", current_msg+1);
  50. X    if (event && event->ie_code == MS_LEFT)
  51. X    value = 0;
  52. X    (void) sprintf(buf, "%s %s %d",
  53. X    (value == 2 || value == 3)? "replyall" : "replysender",
  54. X    (value == 1 || value == 3)? "-i": NO_STRING, current_msg+1);
  55. X    (void) cmd_line(buf, msg_list);
  56. X}
  57. X
  58. X/* following macro is for the next two procedures */
  59. X#define hdr_item (item == sub_hdr_item[0] || item == sub_hdr_item[1] || \
  60. X                  item == sub_hdr_item[2] || item == sub_hdr_item[3] || \
  61. X                  item == sub_hdr_item[4] || item == sub_hdr_item[5])
  62. X
  63. Xdelete_mail(item, value, event)
  64. Xregister Panel_item item;
  65. Xint value;
  66. Xregister struct inputevent *event;
  67. X{
  68. X    int val = value; /* save cuz we reset value immediately */
  69. X    u_long bang = ison(glob_flags, IGN_BANG);
  70. X    char buf[128];
  71. X
  72. X    panel_set(item, PANEL_VALUE, 0, 0);
  73. X    if (hdr_item && event->ie_code != MS_LEFT || val == 2)
  74. X    return help(panel_sw->ts_windowfd, "delete", tool_help);
  75. X    /* delete current message */
  76. X    print(sprintf(buf, "%sdelete %s",
  77. X    ((event->ie_code == MS_LEFT || val == 0)? "" : "un"),
  78. X    panel_get_value(msg_num_item)));
  79. X    turnon(glob_flags, IGN_BANG);
  80. X    (void) cmd_line(buf, msg_list);
  81. X    if (!bang)
  82. X    turnoff(glob_flags, IGN_BANG);
  83. X}
  84. X
  85. Xread_mail(item, value, event)
  86. Xregister Panel_item item;
  87. Xregister int value;
  88. Xregister struct inputevent *event;
  89. X{
  90. X    register int this_msg = current_msg;
  91. X
  92. X    /* check "event" in case we were called from select.c
  93. X     * in which case event would be NULL
  94. X     */
  95. X    if (event && event->ie_code == MS_RIGHT &&
  96. X        item && (item == read_item && value ||
  97. X    (item == sub_hdr_item[0] || item == sub_hdr_item[1])))
  98. X    return help(panel_sw->ts_windowfd, "next", tool_help);
  99. X    if (item && (item == sub_hdr_item[4] || item == sub_hdr_item[5]))
  100. X    return help(panel_sw->ts_windowfd, "msg_menu", tool_help);
  101. X    if (!msg_cnt) {
  102. X    print ("No Mail.");
  103. X    return -1;
  104. X    }
  105. X    if (item && item == read_item || ison(msg[current_msg].m_flags, DELETE))
  106. X    (void) next_msg();
  107. X    if (this_msg != current_msg || ison(msg[current_msg].m_flags, UNREAD) ||
  108. X        (current_msg < n_array[0] || current_msg > n_array[screen])) {
  109. X    set_isread(current_msg);
  110. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  111. X    }
  112. X    if (isoff(msg[current_msg].m_flags, DELETE))
  113. X    display_msg(current_msg, (long)0);
  114. X    return -1;
  115. X}
  116. X
  117. X/* the panel button that says "filename" and "directory", etc... text item */
  118. Xfile_dir(item, event)
  119. XPanel_item item;
  120. Xstruct inputevent *event;
  121. X{
  122. X    register char *p;
  123. X    u_long bang = ison(glob_flags, IGN_BANG);
  124. X    char buf[128], *which = panel_get(item, PANEL_LABEL_STRING);
  125. X
  126. X    if (!strcmp(which, "folder:"))
  127. X    if (event->ie_code == '\n' || event->ie_code == '\r')
  128. X        (void) sprintf(buf, "folder %s", panel_get_value(item));
  129. X    else
  130. X        (void) sprintf(buf, "folder ! %s", panel_get_value(item));
  131. X
  132. X    else if (!strcmp(which, "directory:"))
  133. X    (void) sprintf(buf, "cd %s", panel_get_value(item));
  134. X
  135. X    else if (!msg_cnt)
  136. X    print("No messages to save");
  137. X
  138. X    else if (!strcmp(which, "filename:")) {
  139. X    int x = 1;
  140. X    register char *b = buf;
  141. X    if (event->ie_code == '\n' || event->ie_code == '\r')
  142. X        b += Strcpy(buf, "save  ");
  143. X    else
  144. X        b += Strcpy(buf, "write ");
  145. X    if ((p = panel_get_value(msg_num_item)) && *p)
  146. X        b += Strcpy(b, p);
  147. X    else
  148. X        b += strlen(sprintf(b, "%d", current_msg+1));
  149. X    *b++ = ' ', *b = 0;
  150. X    if (!(p = panel_get_value(item)) || !*p &&
  151. X        (!(p = do_set(set_options, "mbox")) || !*p))
  152. X        p = DEF_MBOX;
  153. X    print(buf), print_more("in %s?", p); /* prompt before adding to cmd */
  154. X    (void) strcpy(b, p); /* now add to command */
  155. X    if ((x = confirm(print_sw->ts_windowfd)) != 'y' && x != MS_LEFT) {
  156. X        print("Message not saved");
  157. X        return;
  158. X    }
  159. X    }
  160. X    turnon(glob_flags, IGN_BANG);
  161. X    (void) cmd_line(buf, msg_list);
  162. X    if (!bang)
  163. X    turnoff(glob_flags, IGN_BANG);
  164. X}
  165. X
  166. Xdo_file_dir(item, value, event)
  167. XPanel_item item;
  168. Xint value;
  169. Xstruct inputevent *event;
  170. X{
  171. X    char buf[92];
  172. X    u_long bang = ison(glob_flags, IGN_BANG);
  173. X    int x; /* used for confirmation */
  174. X
  175. X    if (item == folder_item) {
  176. X    (void) strcpy(buf, "folder ");
  177. X    if (event->ie_code == MS_LEFT) {
  178. X        print("Current folder is: \"%s\"", mailfile);
  179. X        panel_set(file_item, PANEL_LABEL_STRING, "folder:", 0);
  180. X        panel_set(file_item, PANEL_MENU_CHOICE_STRINGS,
  181. X                "Change without updating current folder", 0, 0);
  182. X    } else {
  183. X        if (!value)
  184. X        (void) strcat(buf, "%");
  185. X        else if (value == 1)
  186. X        (void) strcat(buf, "&");
  187. X        else if (value == 2)
  188. X        (void) strcat(buf, "#");
  189. X        else {
  190. X        (void) sprintf(buf, "folder %s",
  191. X                  panel_get(item, PANEL_CHOICE_STRING, value));
  192. X        if (!strcmp(buf+7, "Help"))
  193. X            return help(panel_sw->ts_windowfd, "folder", tool_help);
  194. X        }
  195. X    }
  196. X    } else if (item == cd_item) {
  197. X    (void) strcpy(buf, "cd ");
  198. X    if (event->ie_code == MS_LEFT || !value) {
  199. X        panel_set(file_item, PANEL_LABEL_STRING, "directory:", 0);
  200. X        panel_set(file_item, PANEL_MENU_CHOICE_STRINGS,
  201. X                "Change to specified directory", 0, 0);
  202. X    } else if (value == 1)
  203. X        (void) strcat(buf, "~");
  204. X    else if (value == 2)
  205. X        (void) strcat(buf, "+");
  206. X    else
  207. X        return help(panel_sw->ts_windowfd, "chdir", tool_help);
  208. X    } else if (item == save_item) {
  209. X    (void) strcpy(buf, "save ");
  210. X    if (event->ie_code == MS_LEFT)
  211. X        if (!strcmp("filename:", panel_get(file_item,PANEL_LABEL_STRING))) {
  212. X        event->ie_code = '\n';  /* let file_dir think it got a \n */
  213. X        return file_dir(file_item, event);
  214. X        } else {
  215. X        panel_set(file_item, PANEL_LABEL_STRING, "filename:", 0);
  216. X        panel_set(file_item, PANEL_MENU_CHOICE_STRINGS,
  217. X            "Save message WITHOUT headers", 0,0);
  218. X        print("Type in Main Panel Window a filename to save message");
  219. X        return;
  220. X        }
  221. X    else if (value == 0) {
  222. X        register char *p = panel_get_value(file_item);
  223. X        register char *p2 = panel_get_value(msg_num_item);
  224. X        if ((!p || !*p) && (!(p = do_set(set_options, "mbox")) || !*p))
  225. X        p = DEF_MBOX;
  226. X        print("Save in %s? ", p);
  227. X        if ((x = confirm(panel_sw->ts_windowfd)) != 'y' && x != MS_LEFT) {
  228. X        print("Message not saved");
  229. X        return;
  230. X        }
  231. X        if (p2 && *p2) {
  232. X        (void) strcat(buf, p2);
  233. X        panel_set(msg_num_item, PANEL_VALUE, NO_STRING, 0);
  234. X        (void) strcat(buf, " ");
  235. X        }
  236. X        (void) strcat(buf, p);
  237. X    } else {
  238. X        (void) sprintf(buf, "save %s",
  239. X        panel_get(item, PANEL_CHOICE_STRING, value));
  240. X        if (!strcmp(buf+5, "Help"))
  241. X        return help(panel_sw->ts_windowfd, "save", tool_help);
  242. X    }
  243. X    }
  244. X    turnon(glob_flags, IGN_BANG);
  245. X    (void) cmd_line(buf, msg_list);
  246. X    if (!bang)
  247. X    turnoff(glob_flags, IGN_BANG);
  248. X    panel_set(item, PANEL_VALUE, NO_STRING, 0); /* remove last value */
  249. X}
  250. X
  251. Xtext_done(item, event)
  252. XPanel_item item;
  253. Xstruct inputevent *event;
  254. X{
  255. X    char opt[30], buf[82], cmd[82];
  256. X    register char *p;
  257. X    u_long bang = ison(glob_flags, IGN_BANG);
  258. X    Panel_item which = NO_ITEM;
  259. X    int set_it;
  260. X
  261. X    if ((event->ie_code == '\n' || event->ie_code == '\r') && 
  262. X                 *strcpy(buf, panel_get_value(item))) {
  263. X    (void) strcpy(opt, panel_get(item, PANEL_LABEL_STRING));
  264. X    set_it = (*opt == 'S');
  265. X    if (!(p = index(opt, ' '))) {
  266. X        print("Hmmm... there seems to be a problem here.");
  267. X        return;
  268. X    }
  269. X    ++p;
  270. X    switch(lower(*p)) {
  271. X        case 'o':
  272. X        (void) sprintf(cmd, "%set %s", (set_it)? "s": "uns", buf);
  273. X        which = option_item;
  274. X        when 'i':
  275. X        (void) sprintf(cmd, "%sgnore %s", (set_it)? "i": "uni", buf);
  276. X        which = ignore_item;
  277. X        when 'a':
  278. X        (void) sprintf(cmd, "%slias %s", (set_it)? "a": "una", buf);
  279. X        which = alias_item;
  280. X        otherwise: print("HUH!? (%c)", *p); return;
  281. X    }
  282. X    turnon(glob_flags, IGN_BANG);
  283. X    (void) cmd_line(cmd, msg_list);
  284. X    if (!bang)
  285. X        turnoff(glob_flags, IGN_BANG);
  286. X    }
  287. X    panel_set(input_item, PANEL_VALUE, NO_STRING, 0); /* remove last value */
  288. X    panel_set(item, PANEL_SHOW_ITEM, FALSE, 0);
  289. X}
  290. X
  291. Xdo_help(item, value, event)
  292. XPanel_item item;
  293. Xregister int value;
  294. Xstruct inputevent *event;
  295. X{
  296. X    register char *p, *helpfile = tool_help;
  297. X    switch(value) {
  298. X    case 1: p = "help";
  299. X    when 2: p = "mouse";
  300. X    when 3: p = "windows";
  301. X    when 4: p = "function keys";
  302. X    when 5: p = "hdr_format", helpfile = cmd_help;
  303. X    when 6: p = "msg_list", helpfile = cmd_help;
  304. X    otherwise: p = "general";
  305. X    }
  306. X    (void) help(panel_sw->ts_windowfd, p, helpfile);
  307. X}
  308. X
  309. Xtoolquit(item, value, event)
  310. XPanel_item item;
  311. Xint value;
  312. Xstruct inputevent *event;
  313. X{
  314. X    register int which;
  315. X
  316. X    if (!value || event->ie_code == MS_LEFT) {
  317. X    if (ison(glob_flags, DO_UPDATE)) {
  318. X        do_update(NO_ITEM, 0, NO_EVENT);
  319. X        turnoff(glob_flags, NEW_MAIL);
  320. X        mail_status(0); /* lower flag (if up) print current num of msgs */
  321. X    }
  322. X    wmgr_changestate (tool->tl_windowfd, rootfd, TRUE);
  323. X    wmgr_changelevel (tool->tl_windowfd, parentfd, TRUE);
  324. X    return;
  325. X    } else if (value == 2) {
  326. X    (void) help(panel_sw->ts_windowfd, "quit", tool_help);
  327. X    return;
  328. X    }
  329. X    print("Left updates changes. Middle does not. Right aborts quit.");
  330. X    if ((which = confirm(panel_sw->ts_windowfd)) == MS_RIGHT) {
  331. X    print("Quit aborted.");
  332. X    return;
  333. X    }
  334. X    abort_mail(NO_ITEM, 0);
  335. X    if (which == MS_LEFT)
  336. X    lock_cursors(), copyback();
  337. X    else
  338. X    print("Bye bye");
  339. X    cleanup(0);
  340. X}
  341. X
  342. Xdo_lpr(item, value, event)
  343. XPanel_item item;
  344. Xint value;
  345. Xstruct inputevent *event;
  346. X{
  347. X    char buf[128];
  348. X
  349. X    if (event && (event->ie_code == MS_LEFT || value == 1)) {
  350. X    print("Sending message %d to printer...", current_msg+1);
  351. X    (void) strcpy(buf, "lpr ");
  352. X    if (value)
  353. X        (void) sprintf(buf, "lpr \"%s\"", panel_get_value(msg_num_item));
  354. X    lock_cursors();
  355. X    (void) cmd_line(buf, msg_list);
  356. X    unlock_cursors();
  357. X    } else
  358. X    (void) help(panel_sw->ts_windowfd, "printer", tool_help);
  359. X}
  360. X
  361. Xdo_clear()
  362. X{
  363. X    /* actions that clears window indicates user wants to quit getting opts */
  364. X    if (msg_pix)
  365. X    pr_destroy(msg_pix), msg_pix = (struct pixrect *)NULL;
  366. X    if (getting_opts)
  367. X    getting_opts = 0, unlock_cursors();
  368. X    pw_writebackground(msg_win, 0,0, msg_rect.r_width,msg_rect.r_height,
  369. X               PIX_CLR);
  370. X    txt.x = 5, txt.y = l_height(curfont) - 1;
  371. X}
  372. X
  373. Xdo_update(item, value, event)
  374. XPanel_item item;
  375. Xregister int value;
  376. Xstruct inputevent *event;
  377. X{
  378. X    char *argv[2];
  379. X    if (event && event->ie_code != MS_LEFT)
  380. X    return help(panel_sw->ts_windowfd, "update", tool_help);
  381. X    argv[0] = "update";
  382. X    argv[1] = NULL;
  383. X    (void) folder(0, argv, NULL);
  384. X}
  385. X
  386. X/* panel selction button to send a letter.
  387. X * add a CR if necessary, and finish up letter
  388. X */
  389. Xdo_send(item, value, event)
  390. XPanel_item item;
  391. Xregister int value;
  392. Xregister struct inputevent *event;
  393. X{
  394. X    if (event->ie_code != MS_LEFT)
  395. X    return help(panel_sw->ts_windowfd, "send", tool_help);
  396. X    if (txt.x > 5) {
  397. X    type_cursor(PIX_CLR);
  398. X    add_to_letter(rite('\n')); /* if line isn't complete, flush it */
  399. X    }
  400. X    finish_up_letter();
  401. X}
  402. X
  403. Xdo_edit(item, value, event)
  404. XPanel_item item;
  405. Xregister int value;
  406. Xregister struct inputevent *event;
  407. X{
  408. X    char buf[4];
  409. X    if (event->ie_code != MS_LEFT)
  410. X    return help(panel_sw->ts_windowfd, "edit", tool_help);
  411. X    if (txt.x > 5)
  412. X    add_to_letter(rite('\n')); /* flush line for him */
  413. X    add_to_letter(sprintf(buf, "%cv", *escape));
  414. X}
  415. X
  416. Xdo_compose(item, value, event)
  417. XPanel_item item;
  418. Xregister int value;
  419. Xstruct inputevent *event;
  420. X{
  421. X    if (event && event->ie_code != MS_LEFT)
  422. X    return help(panel_sw->ts_windowfd, "compose", tool_help);
  423. X    print("Composing letter.");
  424. X    win_setcursor(msg_sw->ts_windowfd, &write_cursor);
  425. X    clear_msg_list(msg_list);
  426. X    do_mail(0, DUBL_NULL, msg_list);
  427. X}
  428. X
  429. Xchange_font(item, value, event)
  430. XPanel_item item;
  431. Xregister int value;
  432. Xstruct inputevent event;
  433. X{
  434. X    if (ison(glob_flags, IS_GETTING))
  435. X    type_cursor(PIX_XOR);
  436. X    curfont = value % total_fonts;
  437. X    print("New font: %s\n",
  438. X        (!curfont)? "Normal": (curfont == 1)? "Small": "Large");
  439. X    if (ison(glob_flags, IS_GETTING))
  440. X    type_cursor(PIX_XOR);
  441. X    crt = msg_rect.r_height / l_height(curfont);
  442. X}
  443. END_OF_FILE
  444. if test 12131 -ne `wc -c <'doproc.c'`; then
  445.     echo shar: \"'doproc.c'\" unpacked with wrong size!
  446. fi
  447. # end of 'doproc.c'
  448. fi
  449. if test -f 'file.c' -a "${1}" != "-c" ; then 
  450.   echo shar: Will not clobber existing file \"'file.c'\"
  451. else
  452. echo shar: Extracting \"'file.c'\" \(9633 characters\)
  453. sed "s/^X//" >'file.c' <<'END_OF_FILE'
  454. X/* file.c -- Copyright (1988) Dan Heller */
  455. X
  456. X#include "mush.h"
  457. X#include <pwd.h>
  458. X
  459. X/* takes string 'p' and address of int (isdir).  If p uses the ~ to reference
  460. X * a home directory of some sort, then expand it.  find out what sort of
  461. X * file final path is. set isdir to 1 if a directory, 0 if not, -1 on error
  462. X * return final path. If an error occurs, return string indicating error.
  463. X * if isdir has a value of 1 when passed, it ignores "No such file or directory"
  464. X */
  465. Xchar *
  466. Xgetpath(p, isdir)
  467. Xregister char *p;
  468. Xint *isdir;
  469. X{
  470. X    static char buf[BUFSIZ];
  471. X    struct stat stat_buf;
  472. X
  473. X    if (!p || !*p || !strcmp(p, "~")) {
  474. X    char *home = do_set(set_options, "home");
  475. X    if (!home || !*home)
  476. X        home = ALTERNATE_HOME;
  477. X    (void) strcpy(buf, home);  /* no arg means home */
  478. X    } else if (*p == '~') {
  479. X    if (p[1] != '/') {
  480. X        /* not our home, but someone else's
  481. X         * look for ~user or ~user/subpath
  482. X         * if '/' exists, separate into tmp="user" p="subpath"
  483. X         */
  484. X        struct passwd *ent, *getpwnam();
  485. X        char *p2 = p+1;
  486. X        if (p = index(p2, '/'))
  487. X        *p++ = 0;
  488. X        if (!(ent = getpwnam(p2))) {
  489. X        *isdir = -1;
  490. X        return sprintf(buf, "no such user: %s", p2);
  491. X        }
  492. X        /* append subpath to pathname */
  493. X        if (p && *p)
  494. X        (void) sprintf(buf, "%s/%s", ent->pw_dir, p);
  495. X        /* if *p == NULL, pathname is done (buf), set isdir = 1 */
  496. X        else {
  497. X        *isdir = 1;
  498. X        return strcpy(buf, ent->pw_dir);
  499. X        }
  500. X    } else {
  501. X        char *home = do_set(set_options, "home");
  502. X        if (!home || !*home)
  503. X        home = ALTERNATE_HOME;
  504. X        (void) sprintf(buf, "%s/%s", home, p+2);
  505. X    }
  506. X    } else if (*p == '%') {
  507. X    /* if %user, append user name... else, it's just us */
  508. X    if (!*++p || *p == ' ' || *p == '\t')
  509. X        (void) strcpy(buf, spoolfile);
  510. X    else
  511. X#ifndef HOMEMAIL
  512. X        (void) sprintf(buf, "%s/%s", MAILDIR, p);
  513. X#else /* HOMEMAIL */
  514. X    {
  515. X        char *p2 = do_set(set_options, "home");
  516. X        (void) sprintf(buf, "%s/%s", p2 ? p2 : ALTERNATE_HOME, MAILFILE);
  517. X    } else {
  518. X        int t_isdir = *isdir;
  519. X        char *t, tmp[256];
  520. X        (void) sprintf(tmp, "~%s/%s", p, MAILFILE);
  521. X        t = getpath(tmp, &t_isdir);
  522. X        if (t_isdir == -1) {
  523. X        *isdir = -1;
  524. X        return t;
  525. X        }
  526. X        /* strcpy(buf, t); --buf already has info because it's static */
  527. X    }
  528. X#endif /* HOMEMAIL */
  529. X    } else if (*p == '+') {
  530. X    register char *p2 = do_set(set_options, "folder");
  531. X    if (!p2 || !*p2)
  532. X        p2 = DEF_FOLDER;
  533. X    (void) sprintf(buf, "%s/%s", p2, ++p);
  534. X    if (*buf != '/') {
  535. X        int t_isdir = *isdir;
  536. X        char *t, tmp[256];
  537. X        if (*buf != '~')
  538. X        (void) sprintf(tmp, "~/%s", buf);
  539. X        else
  540. X        (void) strcpy(tmp, buf);
  541. X        t = getpath(tmp, &t_isdir);
  542. X        if (t_isdir == -1) {
  543. X        *isdir = -1;
  544. X        return t;
  545. X        }
  546. X        /* strcpy(buf, t); --buf already has info because it's static */
  547. X    }
  548. X    } else {  /* allow \ to escape the special chars, +, %, ~ */
  549. X    if (*p == '\\')
  550. X        p++;
  551. X    (void) strcpy(buf, p);
  552. X    }
  553. X    if (stat(buf, &stat_buf)) {
  554. X    (void) access(buf, F_OK); /* set errno to the "real" reason */
  555. X    if (errno == ENOENT && *isdir == 1) {
  556. X        *isdir = 0; /* say it's a regular file even tho it doesn't exist */
  557. X        return buf; /* it may be wanted for creating */
  558. X    }
  559. X    *isdir = -1;
  560. X    return sys_errlist[errno];
  561. X    }
  562. X    *isdir = ((stat_buf.st_mode & S_IFDIR) != 0);
  563. X    return buf;
  564. X}
  565. X
  566. X/*
  567. X * Given a filename[pointer] (p), a file pointer, and a mode, file_to_fp
  568. X * opens the file with the mode.
  569. X * If the mode is "r" then we read the file into the file pointer at the
  570. X * end (fseek(fp, 2, 0)).  If the file is opened for writing, then read
  571. X * from the beginning of fp and write it into the file.
  572. X * This is usually called to read .signatures into messages (thus,
  573. X * opening .signature with "r" and writing to the end of fp which is probably
  574. X * the sendmail process or the message file pointer) or to write fortunes into
  575. X * the message buffer: reading fp (the popened fortune) and writing into file.
  576. X */
  577. Xvoid
  578. Xfile_to_fp(p, fp, mode)
  579. Xregister char *p;
  580. Xregister FILE *fp;
  581. Xchar *mode;
  582. X{
  583. X    int     x = 1;
  584. X    char     *file, buf[BUFSIZ];
  585. X    FILE     *tmp_fp;
  586. X
  587. X    if (!p || !*p) {
  588. X    print("specify filename");
  589. X    return;
  590. X    }
  591. X    file = getpath(p, &x);
  592. X    if (x == -1) { /* on error, file contains error message */
  593. X    wprint(file);
  594. X    return;
  595. X    }
  596. X    wprint("%s: ", file);
  597. X    if (x)   /* if x == 1, then path is a directory */
  598. X    wprint("directory.\n");
  599. X    else if (!(tmp_fp = fopen(file, mode))) {
  600. X    wprint("%s\n", sys_errlist[errno]);
  601. X    return;
  602. X    } else if (*mode != 'r') {
  603. X    rewind(fp);
  604. X    for(x = 0; fgets(buf, BUFSIZ, fp); x++)
  605. X        fputs(buf, tmp_fp);
  606. X    } else
  607. X    for(x = 0; fgets(buf, BUFSIZ, tmp_fp); x++)
  608. X        fputs(buf, fp);
  609. X    wprint("%s%d line%s\n", (*mode == 'a')? "added ": "",
  610. X                  x, (x == 1)? "": "s");
  611. X    fflush(fp);
  612. X    fclose(tmp_fp);
  613. X}
  614. X
  615. X/* clear all contents of the file.  Careful that the file is opened for
  616. X * _writing_ --tempfile is opened for reading, so don't try to empty it
  617. X * if you're using ftruncate.   Return -1 on error, 0 on success.
  618. X */
  619. Xemptyfile(fp, fname)
  620. Xregister FILE **fp;
  621. Xregister char *fname;
  622. X{
  623. X    Debug("Emptying \"%s\"\n", fname);
  624. X#ifndef SYSV
  625. X    return ftruncate(fileno(*fp), 0L);
  626. X#else
  627. X    {
  628. X    int omask = umask(077), ret;
  629. X    fclose(*fp);
  630. X    if (!(*fp = fopen(fname, "w")))
  631. X        ret = -1;
  632. X    ret = 0;
  633. X    (void) umask(omask);
  634. X    return ret;
  635. X    }
  636. X#endif /* SYSV */
  637. X}
  638. X
  639. X/*
  640. X * Finds out how many file descriptors are opened.  Useful for making sure
  641. X * no files got opened in subprocedures which were not subsequently closed.
  642. X */
  643. Xnopenfiles(argc)
  644. X{
  645. X    register int nfiles = 0;
  646. X#ifdef MAXFILES
  647. X    register int size = MAXFILES;
  648. X#else
  649. X    register int size = getdtablesize();
  650. X#endif /* MAXFILES */
  651. X
  652. X    if (argc < 2)
  653. X    print("open file descriptors:");
  654. X    while (--size >= 0)
  655. X        if (fcntl(size, F_GETFL, 0) != -1) {
  656. X        if (argc < 2)
  657. X        print_more(" %d", size);
  658. X            ++nfiles;
  659. X        }
  660. X    if (argc < 2)
  661. X    print("\n");
  662. X    return nfiles;
  663. X}
  664. X
  665. X/*
  666. X * Close all "extraneous" file descriptors; return the number closed
  667. X */
  668. Xclosefileds (n)
  669. X{
  670. X    register int nfiles = 0;
  671. X#ifdef MAXFILES
  672. X    register int size = MAXFILES;
  673. X#else
  674. X    register int size = getdtablesize();
  675. X#endif /* MAXFILES */
  676. X
  677. X    while (--size >= n)
  678. X        if (fcntl(size, F_GETFL, 0) != -1) {
  679. X        (void) close(size);
  680. X            ++nfiles;
  681. X        }
  682. X    return nfiles;
  683. X}
  684. X
  685. X/*
  686. X * Open a path for writing or appending -- return a FILE pointer.
  687. X * If program is TRUE, then use popen, not fopen and don't check 
  688. X * to see if the file is writable.
  689. X */
  690. XFILE *
  691. Xopen_file(p, program)
  692. Xregister char *p;
  693. X{
  694. X    register FILE *newfile = NULL_FILE;
  695. X    register char *tmp;
  696. X    int x = 1;
  697. X
  698. X    if (program || *p == '/')
  699. X    tmp = p, x = 0;
  700. X    else
  701. X    tmp = getpath(p, &x);
  702. X    if (x == 1)
  703. X    print("%s is a directory.\n", tmp);
  704. X    else if (x == -1)
  705. X    print("%s: %s\n", p, tmp);
  706. X    else {
  707. X    register char *mode = NULL;
  708. X    /* if it doesn't exist open for "w" */
  709. X    if (program || Access(tmp, F_OK))
  710. X        mode = "w";
  711. X    /* if we can't write to it, forget it */
  712. X    else if (Access(tmp, W_OK))
  713. X        error(tmp);
  714. X    else
  715. X        mode = "a";
  716. X    if (mode)
  717. X        if (program) {
  718. X        if (!(newfile = popen(tmp, mode))) {
  719. X            error("Can't execute %s\n", tmp);
  720. X            return newfile;
  721. X        }
  722. X        } else
  723. X        if (!(newfile = mask_fopen(tmp, mode)))
  724. X            error("Can't write to %s", tmp);
  725. X        else
  726. X        Debug("Successfully opened %s\n", tmp);
  727. X    }
  728. X    return newfile;
  729. X}
  730. X
  731. X/*
  732. X * find_files gets a set of addresses and an array of
  733. X * file pointers and the maximum size that array can be.
  734. X * The object is to find the files or programs listed in "s", attempt
  735. X * to fopen/popen them and save their file pointers in the array. If the
  736. X * size is 0, then just extract the file names and give error messages
  737. X * for each one since they will not be opened. Return the number of
  738. X * files opened and delete all files (opened or not) from the list in
  739. X * "s".  Tokens beginning with a "/, ~, or + are files; tokens beginning
  740. X * with a | are programs.
  741. X * The string "s" is modified to be a list of address -- all names AND
  742. X * files are stripped out of the list.
  743. X */
  744. Xfind_files(s, files, size)
  745. Xregister char *s;
  746. XFILE *files[];
  747. X{
  748. X    register int     total = 0, prog;
  749. X    char          file[MAXPATHLEN], buf[HDRSIZ], *start = s, c;
  750. X    register char    *p, *b = buf;
  751. X
  752. X    do  {
  753. X    if (!(p = get_name_n_addr(s, NULL, file)))
  754. X        break;
  755. X    c = *p, *p = 0;
  756. X    /* It's a file -- try to open it.  This doesn't get written back
  757. X     * onto "buf" since it is supposed to be extracted anyway.
  758. X     */
  759. X    if (*file == '+' || *file == '~' || *file == '|' || *file == '/') {
  760. X        prog = (*file == '|');
  761. X        if (size && total < size) {
  762. X        /* either open "file" or &file[1] */
  763. X        if (files[total] = open_file(&file[prog], prog))
  764. X            total++;
  765. X        } else
  766. X        print("No open space for %s\n", file);
  767. X    } else {
  768. X        b += Strcpy(b, s);
  769. X        *b++ = ',', *b++ = ' ';
  770. X    }
  771. X    for (*p = c, s = p; *s == ',' || isspace(*s); s++)
  772. X        ;
  773. X    } while (*s);
  774. X    for (*b-- = 0; b > buf && (*b == ',' || isspace(*b)); b--)
  775. X    *b = 0;
  776. X    (void) strcpy(start, buf);
  777. X    return total;
  778. X}
  779. X
  780. X/*
  781. X * access(2) has an undocumented feature which ignores suid.  If you are
  782. X * su'ed and try to read your mail, you will be unable to because access()
  783. X * will give the illusion that you cannot read/write to your mbox.  Solve
  784. X * the problem by using stat() instead.
  785. X */
  786. XAccess(file, mode)
  787. Xregister char *file;
  788. X{
  789. X    struct stat buf;
  790. X
  791. X    if (stat(file, &buf) == -1)
  792. X    return -1;
  793. X    if (mode == R_OK)
  794. X    return (buf.st_mode & 0400)? 0 : -1;
  795. X    if (mode == W_OK)
  796. X    return (buf.st_mode & 0200)? 0 : -1;
  797. X    return 0;
  798. X}
  799. X
  800. X/*
  801. X * Open a file for read/write/whatever but make sure umask is rw by user only.
  802. X */
  803. XFILE *
  804. Xmask_fopen(file, mode)
  805. Xchar *file, *mode;
  806. X{
  807. X    int omask = umask(077);
  808. X    FILE *fp = fopen(file, mode);
  809. X    (void) umask(omask);
  810. X    return fp;
  811. X}
  812. END_OF_FILE
  813. if test 9633 -ne `wc -c <'file.c'`; then
  814.     echo shar: \"'file.c'\" unpacked with wrong size!
  815. fi
  816. # end of 'file.c'
  817. fi
  818. if test -f 'signals.c' -a "${1}" != "-c" ; then 
  819.   echo shar: Will not clobber existing file \"'signals.c'\"
  820. else
  821. echo shar: Extracting \"'signals.c'\" \(10419 characters\)
  822. sed "s/^X//" >'signals.c' <<'END_OF_FILE'
  823. X/* @(#)signals.c    (c) copyright 10/18/86 (Dan Heller) */
  824. X
  825. X#include "mush.h"
  826. X
  827. X#ifndef SYSV
  828. Xextern char *sys_siglist[];
  829. X#else
  830. X/* sys-v doesn't have normal sys_siglist */
  831. Xstatic char    *sys_siglist[] = {
  832. X/* no error */  "no error",
  833. X/* SIGHUP */    "hangup",
  834. X/* SIGINT */    "interrupt (rubout)",
  835. X/* SIGQUIT */    "quit (ASCII FS)",
  836. X/* SIGILL */    "illegal instruction (not reset when caught)",
  837. X/* SIGTRAP */    "trace trap (not reset when caught)",
  838. X/* SIGIOT */    "IOT instruction",
  839. X/* SIGEMT */    "EMT instruction",
  840. X/* SIGFPE */    "floating point exception",
  841. X/* SIGKILL */    "kill (cannot be caught or ignored)",
  842. X/* SIGBUS */    "bus error",
  843. X/* SIGSEGV */    "segmentation violation",
  844. X/* SIGSYS */    "bad argument to system call",
  845. X/* SIGPIPE */    "write on a pipe with no one to read it",
  846. X/* SIGALRM */    "alarm clock",
  847. X/* SIGTERM */    "software termination signal from kill",
  848. X/* SIGUSR1 */    "user defined signal 1",
  849. X/* SIGUSR2 */    "user defined signal 2",
  850. X/* SIGCLD */    "death of a child",
  851. X/* SIGPWR */    "power-fail restart"
  852. X};
  853. X#endif /* SYSV */
  854. X
  855. X#ifdef SUNTOOL
  856. Xmsgwin_handlesigwinch()
  857. X{
  858. X    register struct rect rect;
  859. X    if (exec_pid)
  860. X    return;
  861. X    rect = msg_rect;
  862. X    pw_damaged(msg_win);
  863. X    /* this prevents old screen from being lost when editor finishes */
  864. X    if (isoff(glob_flags, IS_GETTING))
  865. X    gfxsw_interpretesigwinch(msg_sw->ts_data);
  866. X    gfxsw_handlesigwinch(msg_sw->ts_data);
  867. X    pw_repairretained(msg_win);
  868. X    pw_donedamaged(msg_win);
  869. X    win_getrect(msg_sw->ts_windowfd, &msg_rect);
  870. X    crt = msg_rect.r_height / l_height(curfont);
  871. X    if (rect.r_height != msg_rect.r_height || rect.r_width != rect.r_width)
  872. X    if (getting_opts == 1)
  873. X        display_opts(0);
  874. X    else if (getting_opts == 2)
  875. X        set_fkeys();
  876. X    else if (msg_pix)
  877. X        scroll_win(0);
  878. X}
  879. X
  880. Xhdrwin_handlesigwinch()
  881. X{
  882. X    register struct rect rect;
  883. X    rect = hdr_rect;
  884. X    pw_damaged(hdr_win);
  885. X    gfxsw_interpretesigwinch(hdr_sw->ts_data);
  886. X    gfxsw_handlesigwinch(hdr_sw->ts_data);
  887. X    pw_repairretained(hdr_win);
  888. X    pw_donedamaged(hdr_win);
  889. X    win_getrect(hdr_sw->ts_windowfd, &hdr_rect);
  890. X    if (rect.r_width != hdr_rect.r_width || rect.r_height != hdr_rect.r_height){
  891. X    pw_writebackground(hdr_win, 0,0,
  892. X               hdr_rect.r_width, hdr_rect.r_height, PIX_CLR);
  893. X    screen = hdr_rect.r_height/l_height(DEFAULT);
  894. X    (void) do_hdrs(0, DUBL_NULL, NULL);
  895. X    }
  896. X}
  897. X
  898. Xprint_sigwinch()
  899. X{
  900. X    pw_damaged(print_win);
  901. X    gfxsw_handlesigwinch(print_sw->ts_data);
  902. X    pw_writebackground(print_win, 0,0,
  903. X        win_getwidth(print_sw->ts_windowfd),
  904. X    win_getheight(print_sw->ts_windowfd), PIX_CLR);
  905. X    pw_donedamaged(print_win);
  906. X    print(NULL);  /* reprint whatever was there before damage */
  907. X}
  908. X
  909. XSIGRET
  910. Xsigwinchcatcher()
  911. X{
  912. X    tool_sigwinch(tool);
  913. X}
  914. X#endif /* SUNTOOL */
  915. X
  916. XSIGRET
  917. Xintrpt(sig)
  918. X{
  919. X    Debug("interrupt() caught: %d\n", sig);
  920. X    mac_flush();
  921. X    turnon(glob_flags, WAS_INTR);
  922. X}
  923. X
  924. X/*
  925. X * catch signals to reset state of the machine.  Always print signal caught.
  926. X * If signals are ignored, return.  If we're running the shell, longjmp back.
  927. X */
  928. X/*ARGSUSED*/
  929. XSIGRET
  930. Xcatch(sig)
  931. X{
  932. X    Debug("Caught signal: %d\n", sig);
  933. X    (void) signal(sig, catch);
  934. X    if (ison(glob_flags, IGN_SIGS) && sig != SIGTERM && sig != SIGHUP)
  935. X    return;
  936. X    mac_flush();
  937. X    print("%s: %s\n", prog_name, sys_siglist[sig]);
  938. X    turnoff(glob_flags, IS_PIPE);
  939. X    if (istool || sig == SIGTERM || sig == SIGHUP) {
  940. X    if (istool) /* istool is 2 if tool is complete */
  941. X        istool = 1;
  942. X    (void) setjmp(jmpbuf);
  943. X    if (ison(glob_flags, IS_GETTING))
  944. X        rm_edfile(-1);
  945. X    cleanup(sig);
  946. X    }
  947. X    if (ison(glob_flags, DO_SHELL)) {
  948. X    /* wrapcolumn may have been trashed -- restore it */
  949. X    if (ison(glob_flags, IS_GETTING)) {
  950. X        char *fix = do_set(set_options, "wrapcolumn");
  951. X        if (fix && *fix)
  952. X        wrapcolumn = atoi(fix);
  953. X    }
  954. X    turnoff(glob_flags, IS_GETTING);
  955. X    longjmp(jmpbuf, 1);
  956. X    } else
  957. X    puts("exiting"), cleanup(sig);
  958. X}
  959. X
  960. X#ifdef SIGCONT
  961. XSIGRET
  962. Xstop_start(sig)
  963. X{
  964. X    extern FILE *ed_fp;
  965. X
  966. X    Debug("Caught signal: %d", sig);
  967. X    if (sig == SIGCONT) {
  968. X    (void) signal(SIGTSTP, stop_start);
  969. X    (void) signal(SIGCONT, stop_start);
  970. X    echo_off();
  971. X    if (istool || ison(glob_flags, IGN_SIGS) && !iscurses)
  972. X        return;
  973. X    /* we're not in an editor but we're editing a letter */
  974. X    if (ison(glob_flags, IS_GETTING)) {
  975. X        if (ed_fp)
  976. X        print("(Continue editing letter)\n");
  977. X    }
  978. X#ifdef CURSES
  979. X    else if (iscurses)
  980. X        if (ison(glob_flags, IGN_SIGS)) {
  981. X        clr_bot_line();
  982. X        if (msg_list)
  983. X            puts(compose_hdr(current_msg));
  984. X        mail_status(1), addstr("...continue... ");
  985. X        refresh();
  986. X        } else {
  987. X        int curlin = max(1, current_msg - n_array[0] + 1);
  988. X        redraw();
  989. X        print("Continue");
  990. X        move(curlin, 0);
  991. X        refresh();
  992. X        /* make sure we lose reverse video on continuation */
  993. X        if (ison(glob_flags, REV_VIDEO) && msg_cnt) {
  994. X            char buf[256];
  995. X            (void) strncpy(buf, compose_hdr(current_msg), COLS-1);
  996. X            buf[COLS-1] = 0; /* strncpy does not null terminate */
  997. X            mvaddstr(curlin, 0, buf);
  998. X        }
  999. X        }
  1000. X#endif /* CURSES */
  1001. X      else
  1002. X        mail_status(1), fflush(stdout);
  1003. X    } else {
  1004. X#ifdef CURSES
  1005. X    if (iscurses) {
  1006. X        /* when user stops mush, the current header is not in reverse
  1007. X         * video -- note that a refresh() has not been called in curses.c!
  1008. X         * so, make sure that when a continue is called, the reverse video
  1009. X         * for the current message returns.
  1010. X         */
  1011. X        turnon(glob_flags, WAS_INTR);
  1012. X        if (isoff(glob_flags, IGN_SIGS) && ison(glob_flags, REV_VIDEO) &&
  1013. X            msg_cnt) {
  1014. X        int curlin = max(1, current_msg - n_array[0] + 1);
  1015. X        char buf[256];
  1016. X        scrn_line(curlin, buf);
  1017. X        STANDOUT(curlin, 0, buf);
  1018. X        }
  1019. X        print("Stopping...");
  1020. X    }
  1021. X#endif /* CURSES */
  1022. X    echo_on();
  1023. X    (void) signal(SIGTSTP, SIG_DFL);
  1024. X    (void) signal(SIGCONT, stop_start);
  1025. X    (void) kill(getpid(), sig);
  1026. X    }
  1027. X}
  1028. X#endif /* SIGCONT */
  1029. X
  1030. X/*ARGSUSED*/
  1031. Xvoid
  1032. Xcleanup(sig)
  1033. X{
  1034. X    char buf[128], c;
  1035. X    if (sig != SIGTERM && sig != SIGHUP && ison(glob_flags, IGN_SIGS))
  1036. X    c = 'n';
  1037. X    else
  1038. X    c = 'y';
  1039. X
  1040. X#ifdef CURSES
  1041. X    if (iscurses)
  1042. X    iscurses = FALSE, endwin();
  1043. X#endif /* CURSES */
  1044. X
  1045. X    echo_on();
  1046. X
  1047. X    if (ison(glob_flags, IS_GETTING))
  1048. X    turnoff(glob_flags, IS_GETTING), dead_letter();
  1049. X    if ((sig == SIGSEGV || sig == SIGBUS) && isoff(glob_flags, IGN_SIGS)
  1050. X    && *tempfile) {
  1051. X    fprintf(stderr, "remove %s [y]? ", tempfile), fflush(stderr);
  1052. X    if (fgets(buf, sizeof(buf), stdin))
  1053. X        c = lower(*buf);
  1054. X    }
  1055. X    if (c != 'n' && *tempfile && unlink(tempfile) && !sig && errno != ENOENT)
  1056. X    error(tempfile);
  1057. X    if (sig == SIGSEGV || sig == SIGBUS) {
  1058. X    if (isoff(glob_flags, IGN_SIGS)) {
  1059. X        fprintf(stderr, "coredump [n]? "), fflush(stderr);
  1060. X        if (fgets(buf, sizeof(buf), stdin))
  1061. X        c = lower(*buf);
  1062. X    }
  1063. X    if (c == 'y')
  1064. X        puts("dumping core for debugging"), abort();
  1065. X    }
  1066. X    exit(sig);
  1067. X}
  1068. X
  1069. Xlong    last_spool_size = -1;    /* declared here cuz it's initialized here */
  1070. X
  1071. X/*
  1072. X * if new mail comes in, print who it's from.  sprintf it all into one
  1073. X * buffer and print that instead of separate print statements to allow
  1074. X * the tool mode to make one print statement. The reason for this is that
  1075. X * when the tool is refreshed (caused by a resize, reopen, move, top, etc)
  1076. X * the last thing printed is displayed -- display the entire line.
  1077. X * return 0 if no new mail, 1 if new mail and -1 if new mail is in system
  1078. X * folder, but current mbox is not system mbox.
  1079. X */
  1080. Xcheck_new_mail()
  1081. X{
  1082. X    int        ret_value;
  1083. X    char        buf[BUFSIZ];
  1084. X    register char  *p = buf;
  1085. X
  1086. X#ifdef SUNTOOL
  1087. X    static int is_iconic, was_iconic;
  1088. X
  1089. X    if (istool) {
  1090. X    timerclear(&(mail_timer.it_interval));
  1091. X    timerclear(&(mail_timer.it_value));
  1092. X    mail_timer.it_value.tv_sec = time_out;
  1093. X    setitimer(ITIMER_REAL, &mail_timer, NULL);
  1094. X    }
  1095. X#endif /* SUNTOOL */
  1096. X    /* if fullscreen access in progress (help), don't do anything */
  1097. X    if (ret_value = mail_size()) {
  1098. X#ifdef CURSES
  1099. X    int new_hdrs = last_msg_cnt;
  1100. X#endif /* CURSES */
  1101. X#ifdef SUNTOOL
  1102. X    /* if our status has changed from icon to toolform, then
  1103. X     * there will already be a message stating number of new
  1104. X     * messages.  reset `n' to msg_cnt so we don't restate
  1105. X     * the same # of new messages upon receipt of yet another new message.
  1106. X     */
  1107. X    if (istool && !(is_iconic = (tool->tl_flags&TOOL_ICONIC)) && was_iconic)
  1108. X        last_msg_cnt = msg_cnt;
  1109. X#endif /* SUNTOOL */
  1110. X    if (last_spool_size > spool_size) {
  1111. X        wprint("Someone changed \"%s\"! Reinitializing...\n", mailfile);
  1112. X        if (isoff(glob_flags, READ_ONLY))
  1113. X        (void) emptyfile(&tmpf, tempfile);
  1114. X        msg_cnt = 0;
  1115. X    }
  1116. X    (void) load_folder(mailfile, 1, NULL);
  1117. X    if (msg_cnt < last_msg_cnt)
  1118. X        turnoff(glob_flags, NEW_MAIL);
  1119. X    else
  1120. X        turnon(glob_flags, NEW_MAIL);
  1121. X    if (istool) {
  1122. X        mail_status(0);
  1123. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  1124. X        bell();
  1125. X    }
  1126. X    if (msg_cnt < last_msg_cnt) {
  1127. X        last_msg_cnt = msg_cnt;
  1128. X        last_spool_size = spool_size;
  1129. X        if (!istool)
  1130. X        mail_status(0);
  1131. X        return 0;
  1132. X    }
  1133. X    p += Strcpy(p, "New mail ");
  1134. X    if (msg_cnt - last_msg_cnt <= 1)
  1135. X        p += strlen(sprintf(p, "(#%d) ", msg_cnt));
  1136. X    else
  1137. X        p += strlen(sprintf(p, "(#%d thru #%d)\n", last_msg_cnt+1,msg_cnt));
  1138. X#ifdef SUNTOOL
  1139. X    /*
  1140. X     * If mush is in tool mode and in icon form, don't update
  1141. X     * last_msg_cnt so that when the tool is opened, print() will
  1142. X     * print the correct number of "new" messages.
  1143. X     */
  1144. X    if (!istool || !(was_iconic = tool->tl_flags & TOOL_ICONIC))
  1145. X#endif /* SUNTOOL */
  1146. X        if (iscurses && isoff(glob_flags, CNTD_CMD))
  1147. X        last_msg_cnt = msg_cnt;
  1148. X        else while (last_msg_cnt < msg_cnt) {
  1149. X        char *p2 = compose_hdr(last_msg_cnt++) + 9;
  1150. X        if (strlen(p2) + (p - buf) >= BUFSIZ-5) {
  1151. X            (void) strcat(p, "...\n");
  1152. X            /* force a break by setting last_msg_cnt correctly */
  1153. X            last_msg_cnt = msg_cnt;
  1154. X        } else
  1155. X            p += strlen(sprintf(p, " %s\n", p2));
  1156. X        }
  1157. X#ifdef CURSES
  1158. X    if (iscurses && isoff(glob_flags, CNTD_CMD)) {
  1159. X        if (new_hdrs - n_array[screen-1] < screen)
  1160. X        (void) do_hdrs(0, DUBL_NULL, NULL);
  1161. X        print("%s ...", buf);
  1162. X    } else
  1163. X#endif /* CURSES */
  1164. X        print("%s", buf); /* buf might have %'s in them!!! */
  1165. X    } else
  1166. X#ifdef SUNTOOL
  1167. X    if (!istool || !is_iconic)
  1168. X#endif /* SUNTOOL */
  1169. X        turnoff(glob_flags, NEW_MAIL);
  1170. X    if (last_spool_size > -1 && /* handle first case */
  1171. X        strcmp(mailfile, spoolfile) && last_spool_size < spool_size)
  1172. X    print("You have new mail in your system mailbox.\n"), ret_value = -1;
  1173. X    last_spool_size = spool_size;
  1174. X    return ret_value;
  1175. X}
  1176. X
  1177. X/*ARGSUSED*/   /* we ignore the sigstack, cpu-usage, etc... */
  1178. XSIGRET
  1179. Xbus_n_seg(sig)
  1180. X{
  1181. X    (void) signal(sig, SIG_DFL);
  1182. X    fprintf(stderr, "%s: %s\n", prog_name,
  1183. X    (sig == SIGSEGV)? "Segmentation violation": "Bus error");
  1184. X    cleanup(sig);
  1185. X}
  1186. END_OF_FILE
  1187. if test 10419 -ne `wc -c <'signals.c'`; then
  1188.     echo shar: \"'signals.c'\" unpacked with wrong size!
  1189. fi
  1190. # end of 'signals.c'
  1191. fi
  1192. if test -f 'strings.c' -a "${1}" != "-c" ; then 
  1193.   echo shar: Will not clobber existing file \"'strings.c'\"
  1194. else
  1195. echo shar: Extracting \"'strings.c'\" \(9787 characters\)
  1196. sed "s/^X//" >'strings.c' <<'END_OF_FILE'
  1197. X/* strings.c Copyright(1988) Dan Heller */
  1198. X
  1199. X#include "mush.h"
  1200. X
  1201. X/*
  1202. X * reverse a string.  Useful for uucp-style address comparisons.
  1203. X */
  1204. Xchar *
  1205. Xreverse(s)
  1206. Xchar s[];
  1207. X{
  1208. X    int n = strlen(s), m;
  1209. X    char c;
  1210. X
  1211. X    if (n < 1)
  1212. X    return;
  1213. X    if (n & 1)
  1214. X    n = n/2 + 1, m = n - 2;
  1215. X    else
  1216. X    n /= 2, m = n - 1;
  1217. X    for ( ; m >= 0; m--, n++)
  1218. X    c = s[n], s[n] = s[m], s[m] = c;
  1219. X    return s;
  1220. X}
  1221. X
  1222. X/*
  1223. X * lose the newline character, trailing whitespace, and return the end of p
  1224. X * test for '\n' separately since some _ctype_[] arrays may not have the
  1225. X * _S bit set for the newline character.  see <ctype.h> for more info.
  1226. X */
  1227. Xchar *
  1228. Xno_newln(p)
  1229. Xregister char *p;
  1230. X{
  1231. X    register char *p2 = p + strlen(p);    /* point it to the null terminator */
  1232. X
  1233. X    while (p2 > p && *--p2 == '\n' || isspace(*p2))
  1234. X    *p2 = 0;  /* get rid of newline and trailing spaces */
  1235. X    return p2;
  1236. X}
  1237. X
  1238. X/* find any character in s1 that's in s2; return pointer to char in s1. */
  1239. Xchar *
  1240. Xany(s1, s2)
  1241. Xregister char *s1, *s2;
  1242. X{
  1243. X    register char *p;
  1244. X    if (!s1 || !*s1 || !s2 || !*s2)
  1245. X    return NULL;
  1246. X    for( ; *s1; s1++) {
  1247. X    for(p = s2; *p; p++)
  1248. X        if (*p == *s1)
  1249. X        return s1;
  1250. X    }
  1251. X    return NULL;
  1252. X}
  1253. X
  1254. X/* check two lists of strings each of which contain substrings.
  1255. X * Each substring is delimited by any char in "delimiters"
  1256. X * return true if any elements in list1 are on list2.
  1257. X * thus:
  1258. X * string1 = "foo, bar, baz"
  1259. X * string2 = "foobar, baz, etc"
  1260. X * delimiters = ", \t"
  1261. X * example returns 1 because "baz" exists in both lists
  1262. X * NOTE: case is ignored.
  1263. X */
  1264. Xchk_two_lists(list1, list2, delimiters)
  1265. Xregister char *list1, *list2, *delimiters;
  1266. X{
  1267. X    register char *p, c;
  1268. X    register int found = 0;
  1269. X
  1270. X    if (p = any(list1, delimiters)) {
  1271. X    for (p++; *p && index(delimiters, *p); p++)
  1272. X        ;
  1273. X    if (chk_two_lists(p, list2, delimiters))
  1274. X        return 1;
  1275. X    }
  1276. X    if (p = any(list2, delimiters)) {
  1277. X    for (p++; *p && index(delimiters, *p); p++)
  1278. X        ;
  1279. X    if (chk_two_lists(list1, p, delimiters))
  1280. X        return 1;
  1281. X    }
  1282. X    if (p) {
  1283. X    while (index(delimiters, *(p-1)))
  1284. X        --p;
  1285. X    c = *p, *p = 0;
  1286. X    }
  1287. X    found = !lcase_strncmp(list1, list2, -1);
  1288. X    if (p)
  1289. X    *p = c;
  1290. X    return found;
  1291. X}
  1292. X
  1293. Xbzero(addr, size)
  1294. Xregister char *addr;
  1295. Xregister int size;
  1296. X{
  1297. X    while (size-- > 0)
  1298. X    addr[size] = 0;
  1299. X}
  1300. X
  1301. X/* do an atoi() on the string passed and return in "val" the decimal value.
  1302. X * the function returns a pointer to the location in the string that is not
  1303. X * a digit.
  1304. X */
  1305. Xchar *
  1306. Xmy_atoi(p, val)
  1307. Xregister char *p;
  1308. Xregister int *val;
  1309. X{
  1310. X    int positive = 1;
  1311. X
  1312. X    if (!p)
  1313. X    return NULL;
  1314. X    *val = 0;
  1315. X    if (*p == '-')
  1316. X    positive = -1, p++;
  1317. X    while (isdigit(*p))
  1318. X    *val = (*val) * 10 + *p++ - '0';
  1319. X    *val *= positive;
  1320. X    return p;
  1321. X}
  1322. X
  1323. X/* strcmp ignoring case */
  1324. Xlcase_strncmp(str1, str2, n)
  1325. Xregister char *str1, *str2;
  1326. X{
  1327. X    while (*str1 && *str2 && --n != 0)
  1328. X    if (lower(*str1) != lower(*str2))
  1329. X        break;
  1330. X    else
  1331. X        str1++, str2++;
  1332. X    return lower(*str1) - lower(*str2);
  1333. X}
  1334. X
  1335. X/* strcpy converting everything to lower case (arbitrary) to ignore cases */
  1336. Xchar *
  1337. Xlcase_strcpy(dst, src)
  1338. Xregister char *dst, *src;
  1339. X{
  1340. X    register char *s = dst;
  1341. X
  1342. X    /* "lower" is a macro, don't increment its argument! */
  1343. X    while (*dst++ = lower(*src))
  1344. X    src++;
  1345. X    return s;
  1346. X}
  1347. X
  1348. X/* this strcpy returns number of bytes copied */
  1349. XStrcpy(dst, src)
  1350. Xregister char *dst, *src;
  1351. X{
  1352. X    register int n = 0;
  1353. X    if (!dst || !src)
  1354. X    return 0;
  1355. X    while (*dst++ = *src++)
  1356. X    n++;
  1357. X    return n;
  1358. X}
  1359. X
  1360. Xvoid
  1361. Xxfree(cp)
  1362. Xchar *cp;
  1363. X{
  1364. X    extern char end[];
  1365. X
  1366. X    if (cp >= end && cp < (char *) &cp && debug < 5)
  1367. X    free(cp);
  1368. X}
  1369. X
  1370. Xchar *
  1371. Xsavestr(s)
  1372. Xregister char *s;
  1373. X{
  1374. X    register char *p;
  1375. X    char *malloc();
  1376. X    if (!s)
  1377. X    s = "";
  1378. X    if (!(p = malloc((unsigned) (strlen(s) + 1)))) {
  1379. X    error("out of memory saving %s", s);
  1380. X    return NULL;
  1381. X    }
  1382. X    return strcpy(p, s);
  1383. X}
  1384. X
  1385. Xvoid
  1386. Xfree_vec(argv)
  1387. Xchar **argv;
  1388. X{
  1389. X    register int n;
  1390. X    if (!argv)
  1391. X    return;
  1392. X    for (n = 0; argv[n]; n++)
  1393. X    xfree(argv[n]);
  1394. X    xfree((char *)argv);
  1395. X}
  1396. X
  1397. X/* copy a vector of strings into one string -- return the end of the string */
  1398. Xchar *
  1399. Xargv_to_string(p, argv)
  1400. Xregister char *p, **argv;
  1401. X{
  1402. X    register int i;
  1403. X    register char *ptr = p;
  1404. X
  1405. X    *p = 0;
  1406. X    if (!argv[0])
  1407. X    return "";
  1408. X    for (i = 0; argv[i]; i++)
  1409. X    ptr += strlen(sprintf(ptr, "%s ", argv[i]));
  1410. X    *--ptr = 0;   /* get rid of the last space */
  1411. X    return ptr;
  1412. X}
  1413. X
  1414. Xchar *
  1415. Xitoa(n)
  1416. X{
  1417. X    static char buf[10];
  1418. X    return sprintf(buf, "%d", n);
  1419. X}
  1420. X
  1421. X/*
  1422. X * There are two different kinds of sprintf() --those that return char * and
  1423. X * those that return int.  System-V returns int (the length of the resulting
  1424. X * string).  BSD has historically returned a pointer to the resulting string
  1425. X * instead. Mush was originally written under BSD, so the usage has always
  1426. X * been to assume the char * method.  Because the system-v method is far more
  1427. X * useful, mush should some day change to use that method, but until then,
  1428. X * this routine was written to allow all the unix'es to appear the same to
  1429. X * the programmer regardless of which sprintf is actually used.  The "latest"
  1430. X * version of 4.3BSD (as of Fall 1988) has changed its format to go from the
  1431. X * historical BSD method to the sys-v method.  It is no longer possible to
  1432. X * simply #ifdef this routine for sys-v --it is now required to use this
  1433. X * routine regardless of which sprintf is notice to your machine.  However,
  1434. X * if you know your system's sprintf returns a char *, you can remove the
  1435. X * define in strings.h
  1436. X */
  1437. X#include <varargs.h>
  1438. X/*VARARGS*/
  1439. X/*ARGSUSED*/
  1440. Xchar *
  1441. XSprintf(va_alist)
  1442. Xva_dcl
  1443. X{
  1444. X    char *buf, *fmt;
  1445. X    va_list ap;
  1446. X
  1447. X    va_start(ap);
  1448. X    buf = va_arg(ap, char *);
  1449. X    fmt = va_arg(ap, char *);
  1450. X#ifdef VPRINTF
  1451. X    (void) vsprintf(buf, fmt, ap);
  1452. X#else
  1453. X    {
  1454. X    FILE foo;
  1455. X    foo._cnt = BUFSIZ;
  1456. X    foo._base = foo._ptr = buf; /* may have to be cast (unsigned char *) */
  1457. X    foo._flag = _IOWRT+_IOSTRG;
  1458. X    (void) _doprnt(fmt, ap, &foo);
  1459. X    *foo._ptr = '\0'; /* plant terminating null character */
  1460. X    }
  1461. X#endif /* VPRINTF */
  1462. X    va_end(ap);
  1463. X    return buf;
  1464. X}
  1465. X
  1466. Xvoid
  1467. Xprint_argv(argv)
  1468. Xchar **argv;
  1469. X{
  1470. X    while (*argv)
  1471. X    if (debug)
  1472. X        printf("(%s) ", *argv++);
  1473. X    else
  1474. X        wprint("%s ", *argv++);
  1475. X    if (debug) {
  1476. X    putchar('\n');
  1477. X    fflush(stdout);
  1478. X    } else
  1479. X    wprint("\n");
  1480. X}
  1481. X
  1482. X/*
  1483. X * putstring -- put a string into a file.  Expand \t's into tabs and \n's
  1484. X * into newlines.  Append a \n and fflush(fp);
  1485. X */
  1486. Xvoid
  1487. Xputstring(p, fp)
  1488. Xregister char *p;
  1489. Xregister FILE *fp;
  1490. X{
  1491. X    for ( ; *p; ++p)
  1492. X    if (*p != '\\')
  1493. X        fputc(*p, fp);
  1494. X    else
  1495. X        switch(*++p) {
  1496. X        case 'n': fputc('\n', fp);
  1497. X        when 't': fputc('\t', fp);
  1498. X        otherwise: fputc(*p, fp);
  1499. X        }
  1500. X    fputc('\n', fp);
  1501. X    fflush(fp);
  1502. X}
  1503. X
  1504. X#define chtoi(c)    ((int)(c) - (int)'0')
  1505. X
  1506. X/* m_xlate(str) converts strings of chars which contain ascii representations
  1507. X *  of control characters appearing in str into the literal characters they
  1508. X *  represent.  The usual curses-mode character expansions (\Cx -> control-x)
  1509. X *  are honored, as are most C escapes.  Unrecognized portions are unchanged.
  1510. X */
  1511. Xchar *
  1512. Xm_xlate (str)
  1513. Xregister char *str;
  1514. X{
  1515. X    register char *r, *s, *t;
  1516. X    int dv, nd;
  1517. X
  1518. X    /*
  1519. X     * r will receive the new string, s will track the old one,
  1520. X     *  and t will step through escape sequences
  1521. X     * This allows the translation to be done in place
  1522. X     */
  1523. X    r = s = str;
  1524. X    while (s && *s) {
  1525. X    if (*s == '\\') {
  1526. X        t = s + 1;
  1527. X        /*
  1528. X         * After each case below, t should point to the character
  1529. X         *  following the escape sequence
  1530. X         */
  1531. X        switch(*t) {
  1532. X        case '\0' :
  1533. X            /*
  1534. X             * Hmmm ... a backslash followed by the string
  1535. X             *  terminator.  Copy the backslash ONLY.
  1536. X             */
  1537. X            *r++ = *s++;
  1538. X            break;
  1539. X        case '0' :
  1540. X        case '1' :
  1541. X        case '2' :
  1542. X        case '3' :
  1543. X        case '4' :
  1544. X        case '5' :
  1545. X        case '6' :
  1546. X        case '7' :
  1547. X            /*
  1548. X             * Convert up to 3 octal digits to their ascii value
  1549. X             */
  1550. X            dv = chtoi(*t++);
  1551. X            for (nd = 0; (isdigit(*t) && (nd < 2)); nd++)
  1552. X            if (chtoi(*t) < 8)
  1553. X                dv = (8 * dv) + chtoi(*t++);
  1554. X            else
  1555. X                break;
  1556. X            if (dv < 256 && dv > 0)
  1557. X            /* Valid octal number escaped */
  1558. X            *r++ = (char)dv;
  1559. X            else
  1560. X            /* Invalid octal number, so copy unchanged */
  1561. X            while (s < t)
  1562. X                *r++ = *s++;
  1563. X            break;
  1564. X        case 'b' :
  1565. X            *r++ = '\b';
  1566. X            t++;
  1567. X            break;
  1568. X        case 'C' :
  1569. X            t++;
  1570. X            if (*t == '?')
  1571. X            *r++ = '\177';
  1572. X            else if (*t == '~')
  1573. X            *r++ = '\036';
  1574. X            else if (*t == '/')
  1575. X            *r++ = '\037';
  1576. X            else if (isalpha(*t) || *t > '\132' && *t < '\140')
  1577. X            *r++ = *t & 037;
  1578. X            else
  1579. X            while (s <= t) *r++ = *s++;
  1580. X            t++;
  1581. X            break;
  1582. X        case 'E' :
  1583. X            *r++ = '\033';
  1584. X            t++;
  1585. X            break;
  1586. X        case 'f' :
  1587. X            *r++ = '\f';
  1588. X            t++;
  1589. X            break;
  1590. X        case 'n' :
  1591. X            *r++ = '\n';
  1592. X            t++;
  1593. X            break;
  1594. X        case 'r' :
  1595. X            *r++ = '\r';
  1596. X            t++;
  1597. X            break;
  1598. X        case 't' :
  1599. X            *r++ = '\t';
  1600. X            t++;
  1601. X            break;
  1602. X        case '\\' :
  1603. X            *r++ = *t++;
  1604. X            break;
  1605. X        default :
  1606. X            /*
  1607. X             * Not recognized, so copy both characters
  1608. X             */
  1609. X            *r++ = *s++;
  1610. X            *r++ = *s++;
  1611. X            break;
  1612. X        }
  1613. X        /*
  1614. X         * Now make sure s also points to the character after the
  1615. X         *  escape sequence, by comparing to t
  1616. X         */
  1617. X        if (t > s)
  1618. X        s = t;
  1619. X    } else
  1620. X        *r++ = *s++;
  1621. X    }
  1622. X    *r = '\0';
  1623. X    return str;
  1624. X}
  1625. X
  1626. X/*
  1627. X * Convert control characters to ascii format (reverse effect of m_xlate()).
  1628. X */
  1629. Xchar *
  1630. Xctrl_strcpy(s_out, s_in, bind_format)
  1631. Xregister char *s_out, *s_in;
  1632. X{
  1633. X    extern char *_unctrl[];
  1634. X    char *start = s_out;
  1635. X
  1636. X    for (; *s_in; s_in++)
  1637. X    if (*s_in == '\n')
  1638. X        *s_out++ = '\\', *s_out++ = 'n';
  1639. X    else if (*s_in == '\r')
  1640. X        *s_out++ = '\\', *s_out++ = 'r';
  1641. X    else if (*s_in == '\t')
  1642. X        *s_out++ = '\\', *s_out++ = 't';
  1643. X    else if (*s_in == ESC)
  1644. X        *s_out++ = '\\', *s_out++ = 'E';
  1645. X    else if (iscntrl(*s_in)) {
  1646. X        if (bind_format)
  1647. X        *s_out++ = '\\', *s_out++ = 'C';
  1648. X        else
  1649. X        *s_out++ = '^';
  1650. X        *s_out++ = _unctrl[*s_in][1];
  1651. X    } else
  1652. X        *s_out++ = *s_in;
  1653. X    *s_out = 0;
  1654. X    return start;
  1655. X}
  1656. END_OF_FILE
  1657. if test 9787 -ne `wc -c <'strings.c'`; then
  1658.     echo shar: \"'strings.c'\" unpacked with wrong size!
  1659. fi
  1660. # end of 'strings.c'
  1661. fi
  1662. echo shar: End of archive 5 \(of 19\).
  1663. cp /dev/null ark5isdone
  1664. MISSING=""
  1665. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  1666.     if test ! -f ark${I}isdone ; then
  1667.     MISSING="${MISSING} ${I}"
  1668.     fi
  1669. done
  1670. if test "${MISSING}" = "" ; then
  1671.     echo You have unpacked all 19 archives.
  1672.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1673. else
  1674.     echo You still need to unpack the following archives:
  1675.     echo "        " ${MISSING}
  1676. fi
  1677. ##  End of shell archive.
  1678. exit 0
  1679.